using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Collections.ObjectModel;

namespace Microsoft.VSPowerToys.PackInstallerDataModel
{
    public static class GrouperMethods
    {
        public static void CurrentlyInstalledGrouper(Collection<ToolItem> tools, SortedList<string, PackItem> groupedItems)
        {
            if (groupedItems != null)
            {
                PackItem installedTools = new PackItem(Strings.InstalledToolsLabel, null);
                PackItem notInstalledTools = new PackItem(Strings.NotInstalledToolsLabel, null);

                foreach (ToolItem tool in tools)
                {
                    if (tool.CurrentlyInstalled)
                    {
                        installedTools.Tools.Add(tool);
                    }
                    else
                    {
                        notInstalledTools.Tools.Add(tool);
                    }
                }

                groupedItems.Add(installedTools.Name, installedTools);
                groupedItems.Add(notInstalledTools.Name, notInstalledTools);
            }
        }

        public static void DefaultGrouper(Collection<ToolItem> tools, SortedList<string, PackItem> groupedItems)
        {
            if (groupedItems != null)
            {
                foreach (ToolItem tool in tools)
                {
                    if (groupedItems.ContainsKey(tool.DefaultTag))
                    {
                        groupedItems[tool.DefaultTag].Tools.Add(tool);
                    }
                    else
                    {
                        groupedItems.Add(tool.DefaultTag, new PackItem(tool.DefaultTag, null));
                        groupedItems[tool.DefaultTag].Tools.Add(tool);
                    }
                }
            }
        }

        public static void ToolNameGrouper(Collection<ToolItem> tools, SortedList<string, PackItem> groupedItems)
        {
            if (groupedItems != null)
            {
                PackItem numberGroup = new PackItem(Strings.NumericLabel, null);
                PackItem aThroughHGroup = new PackItem(Strings.AThroughHLabel, null);
                PackItem iThroughPGroup = new PackItem(Strings.IThroughPLabel, null);
                PackItem qThroughZGroup = new PackItem(Strings.QThroughZLabel, null);
                PackItem otherGroup = new PackItem(Strings.OtherLabel, null);

                foreach (ToolItem tool in tools)
                {
                    string startCharacter = tool.ToolName[0].ToString().ToUpper(Application.CurrentCulture);
                    if (AlphabeticalSortGroupings.NumericCharacters.Contains(startCharacter))
                    {
                        numberGroup.Tools.Add(tool);
                    }
                    else if (AlphabeticalSortGroupings.AThroughHCharacters.Contains(startCharacter))
                    {
                        aThroughHGroup.Tools.Add(tool);
                    }
                    else if (AlphabeticalSortGroupings.IThroughPCharacters.Contains(startCharacter))
                    {
                        iThroughPGroup.Tools.Add(tool);
                    }
                    else if (AlphabeticalSortGroupings.QThroughZCharacters.Contains(startCharacter))
                    {
                        qThroughZGroup.Tools.Add(tool);
                    }
                    else
                    {
                        otherGroup.Tools.Add(tool);
                    }
                }

                groupedItems.Add(numberGroup.Name, numberGroup);
                groupedItems.Add(aThroughHGroup.Name, aThroughHGroup);
                groupedItems.Add(iThroughPGroup.Name, iThroughPGroup);
                groupedItems.Add(qThroughZGroup.Name, qThroughZGroup);
                groupedItems.Add(otherGroup.Name, otherGroup);
            }
        }

        public static void AuthorGrouper(Collection<ToolItem> tools, SortedList<string, PackItem> groupedItems)
        {
            if (groupedItems != null)
            {
                PackItem numberGroup = new PackItem(Strings.NumericLabel, null);
                PackItem aThroughHGroup = new PackItem(Strings.AThroughHLabel, null);
                PackItem iThroughPGroup = new PackItem(Strings.IThroughPLabel, null);
                PackItem qThroughZGroup = new PackItem(Strings.QThroughZLabel, null);
                PackItem otherGroup = new PackItem(Strings.OtherLabel, null);

                foreach (ToolItem tool in tools)
                {
                    string startCharacter = tool.Author[0].ToString().ToUpper(Application.CurrentCulture);
                    if (AlphabeticalSortGroupings.NumericCharacters.Contains(startCharacter))
                    {
                        numberGroup.Tools.Add(tool);
                    }
                    else if (AlphabeticalSortGroupings.AThroughHCharacters.Contains(startCharacter))
                    {
                        aThroughHGroup.Tools.Add(tool);
                    }
                    else if (AlphabeticalSortGroupings.IThroughPCharacters.Contains(startCharacter))
                    {
                        iThroughPGroup.Tools.Add(tool);
                    }
                    else if (AlphabeticalSortGroupings.QThroughZCharacters.Contains(startCharacter))
                    {
                        qThroughZGroup.Tools.Add(tool);
                    }
                    else
                    {
                        otherGroup.Tools.Add(tool);
                    }
                }

                groupedItems.Add(numberGroup.Name, numberGroup);
                groupedItems.Add(aThroughHGroup.Name, aThroughHGroup);
                groupedItems.Add(iThroughPGroup.Name, iThroughPGroup);
                groupedItems.Add(qThroughZGroup.Name, qThroughZGroup);
                groupedItems.Add(otherGroup.Name, otherGroup);
            }
        }

        public static void ReleaseDateGrouper(Collection<ToolItem> tools, SortedList<string, PackItem> groupedItems)
        {
            if (groupedItems != null)
            {
                PackItem lastThirtyDaysGroup = new PackItem(Strings.ReleaseDateGroup30Days, null);
                PackItem lastNinetyDaysGroup = new PackItem(Strings.ReleaseDateGroup90Days, null);
                PackItem lastOneHundredEightyDaysGroup = new PackItem(Strings.ReleaseDateGroup180Days, null);
                PackItem lastThreeHundredSixtyDaysGroup = new PackItem(Strings.ReleaseDateGroup360Days, null);
                PackItem longTimeAgoGroup = new PackItem(Strings.ReleaseDateGroupALongTimeAgo, null);

                foreach (ToolItem tool in tools)
                {
                    DateTime toolReleaseDate = DateTime.Parse(tool.ReleaseDate);
                    TimeSpan toolAge = DateTime.Today - toolReleaseDate;

                    if (toolAge.Days <= 30)
                    {
                        lastThirtyDaysGroup.Tools.Add(tool);
                    }
                    else if (toolAge.Days <= 90)
                    {
                        lastNinetyDaysGroup.Tools.Add(tool);
                    }
                    else if (toolAge.Days <= 180)
                    {
                        lastOneHundredEightyDaysGroup.Tools.Add(tool);
                    }
                    else if (toolAge.Days <= 360)
                    {
                        lastThreeHundredSixtyDaysGroup.Tools.Add(tool);
                    }
                    else
                    {
                        longTimeAgoGroup.Tools.Add(tool);
                    }
                }

                groupedItems.Add(lastThirtyDaysGroup.Name, lastThirtyDaysGroup);
                groupedItems.Add(lastNinetyDaysGroup.Name, lastNinetyDaysGroup);
                groupedItems.Add(lastOneHundredEightyDaysGroup.Name, lastOneHundredEightyDaysGroup);
                groupedItems.Add(lastThreeHundredSixtyDaysGroup.Name, lastThreeHundredSixtyDaysGroup);
                groupedItems.Add(longTimeAgoGroup.Name, longTimeAgoGroup);
            }
        }

        public static void MicrosoftProvidedToolGrouper(Collection<ToolItem> tools, SortedList<string, PackItem> groupedItems)
        {
            if (groupedItems != null)
            {
                PackItem microsoftTools = new PackItem(Strings.MicrosoftProvidedToolsLabel, null);
                PackItem otherTools = new PackItem(Strings.ThirdPartyToolsLabel, null);

                foreach (ToolItem tool in tools)
                {
                    if (tool.MicrosoftProvidedTool)
                    {
                        microsoftTools.Tools.Add(tool);
                    }
                    else
                    {
                        otherTools.Tools.Add(tool);
                    }
                }

                groupedItems.Add(microsoftTools.Name, microsoftTools);
                groupedItems.Add(otherTools.Name, otherTools);
            }
        }
    }

    /// <summary>
    /// Comparer for Pack item objects.
    /// </summary>
    public class DefaultPackItemComparer : IComparer<string>
    {
        private ToolItem.SortByField sortField;
        private bool reverseOrder;

        public DefaultPackItemComparer(ToolItem.SortByField field, SortOrder order)
        {
            this.sortField = field;
            if (order == SortOrder.Descending)
            {
                reverseOrder = true;
            }
        }

        #region IComparer<string> Members

        /// <summary>
        /// Compares two string objects and sort based on the order passed in.
        /// </summary>
        /// <param name="x">Object to compare against</param>
        /// <param name="y">Object to be compared</param>
        /// <returns></returns>
        int IComparer<string>.Compare(string x, string y)
        {
            if (y != null && x != null)
            {
                if (reverseOrder)
                {
                    string temp = x;
                    x = y; y = temp;
                }

                return (x.CompareTo(y));
            }

            throw new ArgumentException(Strings.PackItemCompareToInputErrorMessage);
        }

        #endregion
    }


    /// <summary>
    /// Comparer for Pack item objects.
    /// </summary>
    public class ReleaseDatePackItemComparer : IComparer<string>
    {
        private ToolItem.SortByField sortField;
        private bool reverseOrder;
        private Dictionary<string, ReleaseDateGroups> releaseDateStringMapping;

        private enum ReleaseDateGroups
        {
            Last30Days,
            Last90Days,
            Last180Days,
            Last360Days,
            ALongTimeAgo
        }

        public ReleaseDatePackItemComparer(ToolItem.SortByField field, SortOrder order)
        {
            this.sortField = field;
            if (order == SortOrder.Descending)
            {
                reverseOrder = true;
            }

            releaseDateStringMapping = new Dictionary<string, ReleaseDateGroups>();
            releaseDateStringMapping.Add(Strings.ReleaseDateGroup30Days, ReleaseDateGroups.Last30Days);
            releaseDateStringMapping.Add(Strings.ReleaseDateGroup90Days, ReleaseDateGroups.Last90Days);
            releaseDateStringMapping.Add(Strings.ReleaseDateGroup180Days, ReleaseDateGroups.Last180Days);
            releaseDateStringMapping.Add(Strings.ReleaseDateGroup360Days, ReleaseDateGroups.Last360Days);
            releaseDateStringMapping.Add(Strings.ReleaseDateGroupALongTimeAgo, ReleaseDateGroups.ALongTimeAgo);
        }

        #region IComparer<string> Members

        /// <summary>
        /// Compares two string objects and sort based on the order passed in.
        /// </summary>
        /// <param name="x">Object to compare against</param>
        /// <param name="y">Object to be compared</param>
        /// <returns></returns>
        int IComparer<string>.Compare(string x, string y)
        {
            if (y != null && x != null)
            {
                if (reverseOrder)
                {
                    string temp = x;
                    x = y; y = temp;
                }

                ReleaseDateGroups xValue = releaseDateStringMapping[x];
                ReleaseDateGroups yValue = releaseDateStringMapping[y];

                return (xValue.CompareTo(yValue));
            }

            throw new ArgumentException(Strings.PackItemCompareToInputErrorMessage);
        }

        #endregion
    }
}